#include "readbyteprocess.h"
#include <QDebug>


#define MYLOG qDebug() << "[" << __FILE__ << ":" << __LINE__ << ":" << QThread::currentThread() << __func__ << QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz")<< "]"
ReadbyteProcess::ReadbyteProcess(QObject *parent) : QObject(parent)
{
    //初始化数据库
    initSqlite();

    //获取当天日期
    QDate m_date = QDate::currentDate();
    currentDate = m_date.toString("yyyy-MM-dd");
    if(CurDate != currentDate)
      {
        CurGroupNumber = 1;
      }

    for(int i = 0;i < TargetNumber;i++){
        timer[i] = nullptr;
      }
}

ReadbyteProcess::~ReadbyteProcess()
{
  sqliteTools->closeDataBase();
  if(sqliteTools){
      delete sqliteTools;
      sqliteTools = nullptr;
    }

  for(int i = 0;i < TargetNumber;i++){
      if(timer[i])
        delete timer[i];
      timer[i] = nullptr;
    }

//  delete sqliteThread;
//    sqliteThread = nullptr;
}

//靶标状态，对数据如何进行处理
void ReadbyteProcess::stateProcess(uint16_t onebyte)
{
//    QString byte=QString::number(onebyte,16);
//    uint16_t oneByte=byte.toUShort();
    switch (StateOfMachine) {
        case BeginState:
            if(onebyte==0xBB)
            {
                qDebug()<<&"心跳："[onebyte];
            }
            if(onebyte==relayToServerPrefix)
            {
                StateOfMachine=DateReceveState;
                rawData.clear();
                rawData.append(onebyte);
                qDebug() << "BeginState size:  " << rawData.size();
            }
            break;
        case DateReceveState:
            rawData.append(onebyte);
//            qDebug()<<rawData.size();
            if(rawData.size()==lengthOfTargetData-1)
            {
                StateOfMachine=CheckDateState;
            }
            break;
        case CheckDateState:
            rawData.append(onebyte);
            qDebug()<<"rawDate   :"<<rawData.size();
            //对数据进行校验
                //校验通过对数据进行处理
            if(rawData.size() == 20){
                MYLOG << QString("一帧数据 : %1,%2,%3,%4,%5,%6,"
                                    "%7,%8,%9,%10,%11,%12,%13,%14,%15,%16,%17,%18,%19,%20")
                    .arg(QString::number(rawData[0], 16).toUpper()).arg(QString::number(rawData[1], 16).toUpper()).arg(QString::number(rawData[2], 16).toUpper())
                    .arg(QString::number(rawData[3], 16).toUpper()).arg(QString::number(rawData[4], 16).toUpper()).arg(QString::number(rawData[5], 16).toUpper())
                    .arg(QString::number(rawData[6], 16).toUpper()).arg(QString::number(rawData[7], 16).toUpper()).arg(QString::number(rawData[8], 16).toUpper())
                    .arg(QString::number(rawData[9], 16).toUpper()).arg(QString::number(rawData[10], 16).toUpper()).arg(QString::number(rawData[11], 16).toUpper())
                    .arg(QString::number(rawData[12], 16).toUpper()).arg(QString::number(rawData[13], 16).toUpper()).arg(QString::number(rawData[14], 16).toUpper())
                    .arg(QString::number(rawData[15], 16).toUpper()).arg(QString::number(rawData[16], 16).toUpper()).arg(QString::number(rawData[17], 16).toUpper())
                    .arg(QString::number(rawData[18], 16).toUpper()).arg(QString::number(rawData[19], 16).toUpper());

                if(CheckUtils::CRC16(rawData)) // TODO
                  {
                    qDebug() << "===PASS  CRC===";
                    dateprocess(rawData);// TODO

                  }else{
                    qDebug() << "CRC校验未通过";
                  }
                StateOfMachine = BeginState;
              }
        default:
            StateOfMachine=BeginState;
            rawData.clear();
            break;
    }
}

void ReadbyteProcess::dateprocess(QVector<uint16_t>rawdate)
{
    uint16_t targetID = rawData[1];
    uint16_t bulletSequence = rawData[5];

    // 更新靶标状态到待分配状态
    targetTask.OnlyAdd(targetID,ToBeAssigned);

    // 判断  state ==> 是否为握手信号或者状态位错误
    int parseState = judgeStateBit(rawData[6]);

    if(parseState == stateError){
        qDebug() << &"状态位错误  靶号: " [ targetID];
        return ;
      }

    // 连接状态定时器更新
    updateTimerAndInfo(targetID);
    // 处理温度相关事宜
    judgeTemperature(rawData.mid(7,2));
    // 处理电压事宜
    voltageHandle(targetID,rawData[9]);

    if(parseState == handshakeInfo){
        qDebug() << QString("握手信息 靶号:%1").arg(targetID);
        return ;
      }
    // 判断序列号  ==> 是否是重发数据
    Repeated = judgeBulletSequence(targetID, bulletSequence);

    // 拼接时间
    QVector<uint16_t> deltaTime = jointTime(rawData.mid(10,8));

    // 解算坐标 转换坐标系(原点)  单位:米
    QVector<double> nums = TDOAALG.CoordinateProcessing(deltaTime);

    bulletPoint.X = nums[0];
    bulletPoint.Y = nums[1];

    qDebug() << QString("解算出的X:%1,Y:%2 (单位米)").arg( bulletPoint.X).arg( bulletPoint.Y);

    // 过滤器 ==> 点不属于此靶标
    if(!PointBelongToTheTarget(bulletPoint.X ,bulletPoint.Y)){
        qDebug() << QString("采集器采集到不属于此靶标的数据信息,坐标为: (%1, %2)").arg(bulletPoint.X).arg(bulletPoint.Y);
        //回复中继 EO 数据
        QString msg = targetTask.CreateE0(targetID);

        emit mySignalRelayStringWriteBack(msg);
        return ;
      }

    StateOfTargetMapRwLock.lockForRead();
    if(!StateOfTargetMap.contains(targetID)){
        qDebug() << "靶标ID获取错误,或靶标未连接";
        return ;
      }
    // 获取当前靶标状态
    int curTargetState = StateOfTargetMap[targetID];
    StateOfTargetMapRwLock.unlock();

    // 根据状态判断数据去向
    if(curTargetState==CalibrationTarget)
    {
        calibrationTargetDataHandle(targetID, bulletPoint);

//        MYLOG << QString("校准中....");
    }
    else if(curTargetState==CommonShooting)
    {
        commonShootingHandle(targetID, bulletPoint);
    }
    else if(curTargetState==ToBeAssigned)
    {
        qDebug() << "靶标未分配，如需打靶请分配，如需校准请发送校准指令";
        toBeAssignedHandle(targetID,bulletPoint);
    }
    else
    {
        qDebug() << QString("当前靶标状态不正确: 状态为 ==> %1").arg(curTargetState);
    }
//    switch (curTargetState) {
//      case CalibrationTarget:
//        {
//          calibrationTargetDataHandle(targetID, bulletPoint);

//          MYLOG << QString("校准中....");
//        }
//        break;
//      case CommonShooting:
//        {
//          commonShootingHandle(targetID, bulletPoint);
//        }
//        break;
//      case ToBeAssigned:
//        {
//          qDebug() << "靶标未分配，如需打靶请分配，如需校准请发送校准指令";
//          toBeAssignedHandle(targetID,bulletPoint);
//        }
//        break;
//      default:
//        {
//          qDebug() << QString("当前靶标状态不正确: 状态为 ==> %1").arg(curTargetState);
//        }

//      }
  }


  int ReadbyteProcess::judgeStateBit(uint16_t state)
  {
    // 握手信号处理
    if(state>>4 == 0xF)
      return handshakeInfo;
    // 状态位错误处理
    if((state&0x0F) != 0x0F)
      return stateError;
    return stateNormal;
  }

  QVector<uint16_t> ReadbyteProcess::jointTime(const QVector<uint16_t> &rawTime)
  {
    QVector<uint16_t> res(4, 0);

    if (rawTime.size() < 8) {
        throw runtime_error("数组长度不足");
      }
    res[0] = (rawTime[0] << 8) + rawTime[1];
    res[1] = (rawTime[2] << 8) + rawTime[3];
    res[2] = (rawTime[4] << 8) + rawTime[5];
    res[3] = (rawTime[6] << 8) + rawTime[7];

    return res;
  }

  void ReadbyteProcess::updateTimerAndInfo(uint16_t ID)
  {
    qDebug() << QString("%1号靶已连接").arg(ID);
    if (TimeMap.contains(ID)) {
        QTimer* timer = TimeMap.value(ID);

        //先重新填充值再start会重新计时
        timer->setInterval(MaximumWaitTime * 1000);
        timer->start(); // 将秒转换为毫秒
      } else {
        timer[ID] = new QTimer();
        TimeMap.insert(ID, timer[ID]);
        timer[ID]->setInterval(MaximumWaitTime * 1000);
        timer[ID]->start(); // 将秒转换为毫秒
        QObject::connect(timer[ID], &QTimer::timeout, [=]() {
            targetTask.DeleteVoltage(ID);
            targetTask.ToUnconnected(ID);
            targetTask.DeleteTimer(ID);
            qDebug() << QString("%1号靶,超时重置: 断开连接...").arg(ID);
          });
      }
  }

  void ReadbyteProcess::judgeTemperature(QVector<uint16_t> rawTemp)
  {
    double curTemperature = (double(rawTemp[0]<<8) + double(rawTemp[1])) / 10.0;
    targetTask.UpdateSoundSpeed(curTemperature);
  }

  void ReadbyteProcess::voltageHandle(uint16_t addr, uint16_t voltage)
  {
    targetTask.UpdateVoltage(addr,double(voltage) / 10.0);
  }

  bool ReadbyteProcess::judgeBulletSequence(uint16_t ID, int curSequenceNum)
  {
    // 判断弹序是否更新
    int preSequence = RecordSequenceMap[ID]; // 判断该靶号是否存在

    if (preSequence == curSequenceNum) {
        qDebug() << QString("弹序重复: 靶标ID:%1 上次弹序:%2  此次弹序:%3").arg(ID).arg(preSequence).arg(curSequenceNum);
        return true;
      }
    RecordSequenceMap[ID] = curSequenceNum;
    return false;
  }

  bool ReadbyteProcess::PointBelongToTheTarget(double X, double Y)
  {
    if(X - BorderMinimumAccuracy <= HorizonMin ||
       Y - BorderMinimumAccuracy <= VerticalMin ||
       X > MaxAvailabilityRangeX - BorderMinimumAccuracy ||
       Y > MaxAvailabilityRangeY - BorderMinimumAccuracy)
      return false;
    return true;
  }


  void ReadbyteProcess::calibrationTargetDataHandle(uint16_t ID, BulletPoint point)
  {
    Container[ID].append(point);
    qDebug() << QString("校准%1号靶,数据加一").arg(ID);
    emit mySignalRelayStringWriteBack(targetTask.Create00(ID));
  }

  void ReadbyteProcess::commonShootingHandle(uint16_t ID, BulletPoint point)
  {
    // 正常打靶流程
    qDebug() << "========= 正常打靶流程 =========";

    // 类型转换一下
    int curAddr = ID;

    //获取全局变量
    double leftDownX = TargetConfig.RakesMap[QString::number(curAddr)].LeftDownPoint.X;
    double leftDownY = TargetConfig.RakesMap[QString::number(curAddr)].LeftDownPoint.Y;
    double rightUpX = TargetConfig.RakesMap[QString::number(curAddr)].RightUpPoint.X;
    double rightUpY = TargetConfig.RakesMap[QString::number(curAddr)].RightUpPoint.Y;

    //缩放映射 已修改
    double curSFX = TargetConfig.RakesMap[QString::number(curAddr)].ScaleFactor.X;
    double curSFY = TargetConfig.RakesMap[QString::number(curAddr)].ScaleFactor.Y;

    qDebug() << "leftDownX : " << leftDownX << "leftDownY : " << leftDownY
             << "rightUpX : " << rightUpX << "rightUpY : " << rightUpY << "curSFX : " << curSFX << "curSFY : " << curSFY;

    // 存数据库
    Target_Info_Table targetInfoTable;
    targetInfoTable.addr = curAddr;
    targetInfoTable.x = 0;
    targetInfoTable.y = 0;
    targetInfoTable.SystemID = SystemID;
    targetInfoTable.cylinder_number = 0;
    targetInfoTable.direction = -1;
    targetInfoTable.group_number = CurGroupNumber;
    targetInfoTable.UserId = targetTask.GetUserIdByAddr(curAddr);
    targetInfoTable.CreateAt = currentDate;

    // 过滤数据
    if (IsUndershootPoint(point, leftDownX, leftDownY, rightUpX, rightUpY)) {
        qDebug() << QString("----脱靶的点----,坐标为: %1, %2").arg(point.X).arg(point.Y);

        OneTaregtBullet oneTaregtBullet;
        oneTaregtBullet.addr = curAddr;
        oneTaregtBullet.x = 0;
        oneTaregtBullet.y = 0;
        oneTaregtBullet.cylinder_number = 0;
        oneTaregtBullet.direction = -1;

        if (!Repeated) {
            sqliteTools->insertRecord(targetInfoTable);
          }
        emit mySignalTargetInfo(oneTaregtBullet);
        // 回复中继 FO 数据
        emit mySignalRelayStringWriteBack(targetTask.CreateF0(curAddr));
        return;

      }

    point.X = (point.X - leftDownX) * C;

    point.Y = (point.Y - leftDownY) * C;

    qDebug() << QString("单位转换为像素点X:%1, Y:%2").arg(point.X).arg(point.Y);

    point.X *= curSFX;
    point.Y *= curSFY;

    qDebug() << QString("缩放映射之后:X:%1, Y:%2 ").arg( point.X).arg( point.Y);
    //  判断方向
    int dir = Direction(point.X,point.Y);
    //  计算环数
    int cn = Points(int(point.X),int(point.Y));
    qDebug() << QString("方向: %1 环数: %2 ").arg(dir).arg(cn);

    // 存数据库
    targetInfoTable.addr = curAddr;
    targetInfoTable.x = point.X;
    targetInfoTable.y = point.Y;
    targetInfoTable.SystemID = SystemID;
    targetInfoTable.cylinder_number = cn;
    targetInfoTable.direction = dir;
    targetInfoTable.group_number = CurGroupNumber;
    targetInfoTable.UserId = targetTask.GetUserIdByAddr(curAddr);
    targetInfoTable.CreateAt = currentDate;

    if(!Repeated){
        sqliteTools->insertRecord(targetInfoTable);
      }

    // 获取 rawTargetData 的第三个元素（假设 rawTargetData 是一个数组或类）
    int sequence = rawData[5];

    // 计算 cn << 4 + dir
    int cnDirValue = (cn << 4) + dir;

    // 获取 point 的 X 和 Y 坐标
    int pointXHigh = static_cast<int>(point.X) >> 8;
    int pointXLow = static_cast<int>(point.X) & 0xFF;
    int pointYHigh = static_cast<int>(point.Y) >> 8;
    int pointYLow = static_cast<int>(point.Y) & 0xFF;


    QString msg = targetTask.CommonTargetDataMsg(curAddr, sequence, cnDirValue, pointXHigh, pointXLow, pointYHigh, pointYLow);
    emit mySignalRelayStringWriteBack(msg);

    OneTaregtBullet oneTaregtBullet;
    oneTaregtBullet.addr = curAddr;
    oneTaregtBullet.x = point.X;
    oneTaregtBullet.y = point.Y;
    oneTaregtBullet.cylinder_number = cn;
    oneTaregtBullet.direction = dir;
    qDebug() << "当前子弹触发信号";
    emit mySignalTargetInfo(oneTaregtBullet);
  }

  bool ReadbyteProcess::IsUndershootPoint(BulletPoint p, double ldx, double ldy, double rux, double ruy)
  {
    if(p.X < ldx || p.X > rux || p.Y < ldy || p.Y > ruy)
      return true;
    return false;
  }

  int ReadbyteProcess::Direction(double x1, double y1)
  {
    const double pi = 3.14159;
    int dir = 0;      // 方向
    double x0 = 401.0; // 10环中心点坐标(x0,y0)
    double y0 = 322.0;
    double angle = (180 / pi) * std::atan2(x1 - x0, y1 - y0); // 计算的角度值
    if ((x1 >= x0 && y1 >= y0) || (x1 >= x0 && y1 <= y0))
      {

      }
    else if ((x1 < x0 && y1 < y0) || (x1 < x0 && y1 > y0))
      {
        angle = 360 + angle;
      }
    dir = static_cast<int>((angle + 15) / 30);
    if (dir == 0)
      {
        dir = 12;
      }
    return dir;
  }

  int ReadbyteProcess::Points(int x1, int y1){
    int x2 = 0;

    for (int i = 0; i <= pp.size() - 1; i++) {
        if (y1 == pp[i][1]) {
            if (x1 > 401) {
                x2 = 801 - x1;
              } else {
                x2 = x1;
              }
            if (pp[i][0] > x2) {
                return 0;
              } else {
                break;
              }
          }
      }

    int cn;
    double d;
    double r = 80.1;
    double buDia = DiameterOfBulletPx;

    d = pow(x2 - 401, 2) + pow(y1 - 322, 2);

    if (d < pow(r + buDia, 2)) {
        cn = 10;
      } else if (d >= pow(r + buDia, 2) && d < pow(2 * r + buDia, 2)) {
        cn = 9;
      } else if (d >= pow(2 * r + buDia, 2) && d < pow(3 * r + buDia, 2)) {
        cn = 8;
      } else if (d >= pow(3 * r + buDia, 2) && d < pow(4 * r + buDia, 2)) {
        cn = 7;
      } else if (d >= pow(4 * r + buDia, 2) && d < pow(5 * r + buDia, 2)) {
        cn = 6;
      } else if (d >= pow(5 * r + buDia, 2) && d < pow(6 * r + buDia, 2)) {
        cn = 5;
      } else if (d >= pow(6 * r + buDia, 2) && d < pow(7 * r + buDia, 2)) {
        cn = 4;
      } else {
        cn = 0;
      }
    return cn;
  }

  void ReadbyteProcess::toBeAssignedHandle(uint16_t ID, BulletPoint point)
  {
    qDebug() << "靶标和人员未绑定,已赋初值";
    // 优化项 TargetBelongTOUser 封装读写方法对外提供更好
    targetTask.Update(ID, 3);
    targetTask.Binding(ID, 0);
    commonShootingHandle(ID, point);
  }

  void ReadbyteProcess::deleteRecord(int ID)
  {
    sqliteTools->deleteRecord(ID);
  }

  void ReadbyteProcess::getTargetName(int ID)
  {
    sqliteTools->deleteRecord(ID);
  }

  void ReadbyteProcess::initSqlite()
  {
    sqliteTools = new SQLiteTools(":/autoTarget.db","conn_10");
    sqliteTools->initDataBase();
    sqliteTools->createTable();
    sqliteTools->deleteRecord(-1);
  }

  void ReadbyteProcess::getTargetGroupnumber(int groupnumber)
  {
//    sqliteThread->getGroupNumber(groupnumber);
  }

  void ReadbyteProcess::GetSearchDate(int groupNumber,int addr,QString time)
  {
    searchDate.clear();
    searchDate=sqliteTools->searchGradeTable(groupNumber,addr,time);
  }
